/* 
  Bootloader for MIPS32S
  Chen Yuheng
  2012/07/16
 */

.equ FLASH_START    , 0xbfc00000
.equ BOOT_SIZE      , 0x00000200
.equ KERNEL_SIZE_LOC, (FLASH_START + 0x1fe)
.equ KERNEL_START   , (FLASH_START + BOOT_SIZE)
.equ FLASH_SIZE     , 0x00100000
.equ ELF_MAGIC      , 0x464C457F

.equ KERNEL_LOAD_ADDR, 0xa0000000
.equ KERNEL_START_ADDR, 0x80000000

.equ GPIO_BASE   , 0xbfd0f000

.equ LED_RG_BASE , 0xbfd0f004
.equ LED_RG0_ADDR, 0xbfd0f004 # right
.equ LED_RG1_ADDR, 0xbfd0f008 # left
.equ LED_RG0_OFF , 0x0004
.equ LED_RG1_OFF , 0x0008
.equ LED_RG_BLANK, 0x0000
.equ LED_RG_GREEN, 0x0001
.equ LED_RG_RED  , 0x0002

.equ NUM_ADDR, 0xbfd0f010 # number display
.equ NUM_OFF , 0x0010

#define WRITE_GPIO(off, value) \
  la $t7, GPIO_BASE; \
  addiu $t7, $t7, off; \
  sw value, 0($t7);

.set noreorder
.set noat
.globl __start
__start:

#   jal init_serial
#   nop

#   li $a0, 'i'
#   jal write_serial
#   nop

#   li $a0, 'n'
#   jal write_serial
#   nop

#   li $a0, 'i'
#   jal write_serial
#   nop

#   li $a0, 't'
#   jal write_serial
#   nop

#   li $a0, ' '
#   jal write_serial
#   nop

#   li $a0, 's'
#   jal write_serial
#   nop

#   li $a0, 'e'
#   jal write_serial
#   nop

#   li $a0, 'r'
#   jal write_serial
#   nop

#   li $a0, 'i'
#   jal write_serial
#   nop

#   li $a0, 'a'
#   jal write_serial
#   nop

#   li $a0, 'l'
#   jal write_serial
#   nop

#   li $a0, '\n'
#   jal write_serial
#   nop

#   li $a0, '\r'
#   jal write_serial
#   nop

# .read_char:
#   jal read_serial
#   nop
#   move $a0, $v0
#   jal write_serial
#   nop
#   j .read_char
#   nop

  li $s0, LED_RG_RED
  li $s1, LED_RG_GREEN

  WRITE_GPIO(LED_RG1_OFF, $s0)
  WRITE_GPIO(LED_RG0_OFF, $s1)

  la $s0, KERNEL_SIZE_LOC
  lhu $s0, 0($s0)
  WRITE_GPIO(NUM_OFF, $s0)
  sll $s0, $s0, 9
  la $s1, KERNEL_START
  la $s2, KERNEL_LOAD_ADDR

load:
  lw $t0, 0($s1)
  sw $t0, 0($s2)
  addiu $s1, $s1, 4
  addiu $s2, $s2, 4
  addiu $s0, $s0, -4
  srl $t0, $s0, 9
  WRITE_GPIO(NUM_OFF, $s0)
  bnez $s0, load
  nop

  li $s0, LED_RG_GREEN
  WRITE_GPIO(LED_RG1_OFF, $s0)
  WRITE_GPIO(LED_RG0_OFF, $s0)

  la $k0, KERNEL_START_ADDR
  jr $k0
  nop

  li $s0, LED_RG_RED

  WRITE_GPIO(LED_RG1_OFF, $s0)
  WRITE_GPIO(LED_RG0_OFF, $s0)

bad:
  b bad
  nop

# init_serial:
#   lui $t0, 0xbfe4

#   li $t1, 0x1|0x2|0x4
#   sb $t1, 2($t0)
#   li $t1, 0x80
#   sb $t1, 3($t0)
#   li $t1, 0x23
#   sb $t1, 0($t0)
#   srl $t1, 8
#   sb $t1, 1($t0)

#   li $t1, 0x3
#   sb $t1, 3($t0)
#   li $t1, 0x1|0x2
#   sb $t1, 4($t0)
#   li $t1, 0x1
#   sb $t1, 1($t0)
#   jr $ra
#   nop

# read_serial:
#   lui $t1, 0xbfe4
# .rwait:
#   lb $t1, 5($t1)
#   andi $t0, $t0, 0x01
#   bne $t0, $zero, .rdone
#   nop
#   j .rwait
#   nop
# .rdone:
#   lb $v0, 0($t1)
#   jr $ra
#   nop

# write_serial:
#   lui $t1, 0xbfe4
# .wwait:
#   lb $t0, 5($t1)
#   andi $t0, $t0, 0x20
#   beq $t0, $zero, .wwait
#   nop
# .wdone:
#   sb $a0, 0($t1)
#   jr $ra
#   nop
